<?php

#	Fastfoo - CMS developer under CakePHP / http://fast-foo.com
#	Copyright (C) 2010  Antonio Irlandés García

#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.

#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.

#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.


//Para limpiar Datos
App::import('Sanitize');

class AppController extends Controller{

	//Helpers a usar
	public $helpers = array('Html','Ajax','Javascript','Session','Renderer');

	//Componentes a usar
	public $components = array('Acl', 'Auth', 'RequestHandler', 'Session', 'Email', 'Plugins');
	
	//Modelos a usar
	public $uses = array('Config','Log','User', 'Menu');

	//Hacemos uso de los Temas
 	public $view = 'Theme';

	//theme por defecto
    public $theme = 'default';

	//Configuraciones generales BD
	public $config_general;

	//Configuraciones de los plugins
	public $config_plugins;


    public function beforeFilter(){

		####RECONSTRUYE LAS LISTAS ACL####
		//$this->buildAcl();

		####VARIABLES INICIALES####
		$this->_getParamsMain();

  		####CONFIGURAR AUTH COMPONENT####
		$this->_setAuthConfig();

		####COMPONENTE DE ENVIO DE CORREO####
		$this->_setServerMail();

		####VARIABLES PLUGINS####
		if(!empty($this->Plugins->options_plugins)){
			$this->config_plugins = $this->Plugins->options_plugins;
			$this->set('config_plugins', $this->config_plugins);
		}

		####SESION USER GUEST####
		$this->_setSessionUser();

		########OTRAS###############
		//Titulo de la pagina
		$this->set('title_for_layout', $this->config_general['title_web']);

    }

	public function beforeRender() {

		//Comprueba si existe algún error tipo 404 o así
		if(!$this->_setErrorLayout()){
			//Hacer algo
		}
	}


	/**
	 * Obtiene las variables de la configuración general
	 *
	 * @return void
	 */
	private function _getParamsMain() {
		foreach($this->Config->find("all") as $data_config){
			$this->config_general[$data_config['Config']['data']] = $data_config['Config']['value']; 
		}

		//Idioma
		Configure::write('Config.language', $this->config_general['system_language']);

		//Theme
		$this->theme = $this->config_general['system_theme'];

		//Seteo todas la variables para las vistas
		$this->set('config_general', $this->config_general);
	}

	/**
	 * Configura los parametros de autenticación
	 *
	 * @return void
	 */
	private function _setAuthConfig(){
        $this->Auth->authorize = 'actions';
        $this->Auth->logoutRedirect = Router::url('/');
		$this->Auth->loginRedirect = array('controller' => 'logs', 'action' => 'index', 'admin' => true);//Vista administracion
		$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login', 'admin' => false);//Vista administracion
		//Indica desde donde intentamos realizar el login de usuarios
		$routing_prefixes = Configure::read('Routing.prefixes');
		if(!preg_match('/'.$routing_prefixes[0].'/i', $this->referer())){
			$this->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'view', 'home');//Vista web
		}
		$this->Auth->authError = __("area_required_permissions", true);
		$this->Auth->loginError = __("data_into_no_correctly", true);
		//indica el padre de las acciones de los controladors en la BD (nodo raiz del arbol)
		$this->Auth->actionPath = 'controllers/';
		//Criterio adicional para el logueo
		$this->Auth->userScope = array('User.active' => 1);

		//Acciones permitidas
 		//$this->Auth->allowedActions = array('*');
	}

	/**
	 * Configura los parametros del servidor de correo
	 *
	 * @return void
	 */
	private function _setServerMail(){
		$this->Email->delivery = 'smtp';
		$this->Email->smtpOptions = array(
			'port'=>$this->config_general['smtp_port'], 
			'timeout'=>'30',
			'host' => $this->config_general['smtp_server'],
			'username'=>$this->config_general['smtp_user'],
			'password'=>$this->config_general['smtp_pass']
		);
	}

	/**
	 * Obtiene las variables de sesión del usuario
	 *
	 * @return void
	 */
	private function _setSessionUser(){
		//variables de la sesion iniciada
		if(!$this->Session->check('Auth.User')){	
			//Obtenemos datos del usuario guest (invitado)
			$data_register = $this->User->FindByUsername('guest');			

			if(!empty($data_register['User'])){
				//Elimino la variable password por motivos de seguridad
				unset($data_register['User']['password']);
				$this->Session->write('Auth.User',$data_register['User']);
			}else{
				$this->Session->setFlash('user_guest_no_exist', 'default', array('class' => 'info_sys_error'), 'msg_sys');		
			}
		}
		//Variables de session
		$this->set('data_session', $this->Session->read('Auth.User'));
	}

	/**
	 * Comprueba si existe un error en la paǵina y lo muestra con su estilo correspondiente
	 *
	 * @return void
	 */
	private function _setErrorLayout() {
		if ($this->name == 'CakeError') {
			$this->layout = 'error';
			return true;
		}
			return false;
	}

	/**
	 * Envia correos de notificación
	 *
	 * @return void
	 */
	public function sendMail($options){

		$this->autoRender = false;
		
		$result = true;

		//Datos del Email
		$this->Email->to = $options['to_mail']; 
		$this->Email->subject = $options['subject_mail'];
		$this->Email->from = $this->config_general['email_admin'];
		$this->Email->template = 'notification_mail';
		$this->Email->sendAs = 'html';
		$this->set('text_mail', $options['text_mail']);

		//Enviamos el Email
		if(!$this->Email->send()){
			$msg_result = $this->Email->smtpError;
			$result = false;
		}else{
			$msg_result = "email_send_correctly";
			$result = true;
		}

		$this->Session->setFlash(__($msg_result, true), 'default');

		return $result;

	}


	/**
	 * Reconstruye el Acl basado en los controladores actuales de la aplicación.
	 *
	 * @return void
	 */
    function buildAcl() {
        $log = array();
 
        $aco =& $this->Acl->Aco;
        $root = $aco->node('controllers');
        if (!$root) {
            $aco->create(array('parent_id' => null, 'model' => null, 'alias' => 'controllers'));
            $root = $aco->save();
            $root['Aco']['id'] = $aco->id; 
            $log[] = 'Creado el nodo Aco para los controladores';
        } else {
            $root = $root[0];
        }   
 
        App::import('Core', 'File');
        $Controllers = Configure::listObjects('controller');
        $appIndex = array_search('App', $Controllers);
        if ($appIndex !== false ) {
            unset($Controllers[$appIndex]);
        }
        $baseMethods = get_class_methods('Controller');
        $baseMethods[] = 'buildAcl';
 
		$Plugins = $this->_get_plugin_controller_names();
        $Controllers = array_merge($Controllers, $Plugins);


        // miramos en cada controlador en app/controllers
        foreach ($Controllers as $ctrlName) {
            App::import('Controller', $ctrlName);
            $ctrlclass = $ctrlName . 'Controller';
            $methods = get_class_methods($ctrlclass);
 
            //buscar / crear nodo de controlador
            $controllerNode = $aco->node('controllers/'.$ctrlName);
            if (!$controllerNode) {
                $aco->create(array('parent_id' => $root['Aco']['id'], 'model' => null, 'alias' => $ctrlName));
                $controllerNode = $aco->save();
                $controllerNode['Aco']['id'] = $aco->id;
                $log[] = 'Creado el nodo Aco del controlador '.$ctrlName;
            } else {
                $controllerNode = $controllerNode[0];
            }
 
            //Limpieza de los metodos, para eliminar aquellos en el controlador 
            //y en las acciones privadas
            foreach ($methods as $k => $method) {
                if (strpos($method, '_', 0) === 0) {
                    unset($methods[$k]);
                    continue;
                }
                if (in_array($method, $baseMethods)) {
                    unset($methods[$k]);
                    continue;
                }
                $methodNode = $aco->node('controllers/'.$ctrlName.'/'.$method);
                if (!$methodNode) {
                    $aco->create(array('parent_id' => $controllerNode['Aco']['id'], 'model' => null, 'alias' => $method));
                    $methodNode = $aco->save();
                    $log[] = 'Creado el nodo Aco para '. $method;
                }
            }
        }
        debug($log);
    }


 	/**
     * Obtener los nombres de los controladores de plugins
     * 
     * Esta funcion entrega un arreglo con los nombres de los controladores 
     * de los plugins y además se asegura que los controladores están disponibles
     * para nosotros, de modo de obtener los nombres de los metodos al hacer un 
     * App:import para cada uno de los plugins.

     *
     * @return arreglo con los nombres de los plugins.
     *
     */
    private function _get_plugin_controller_names(){
        App::import('Core', 'File', 'Folder');
        $paths = Configure::getInstance();
        $folder =& new Folder();
        // Cambiamos al directorio de plugins
        $folder->cd(APP.'plugins');
        // Obtener la lista de los archivos que terminan con
        // controller.php
        $files = $folder->findRecursive('.*_controller\.php');
        // Obtener la lista de plugins
        $Plugins = Configure::listObjects('plugin');

        // Ciclo a través de los controladores que encontramos en el
        // directorio de plugins
        foreach($files as $f => $fileName)
        {
            // Obtener el nombre de archivo base
            $file = basename($fileName);

            // Obtener el nombre del controlador
            $file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));

            // Ciclo a través de los plugins
            foreach($Plugins as $pluginName){
                if (preg_match('/^'.$pluginName.'/', $file)){
                    // Primero nos deshacemos del AppController del plugin
                    // Hacemos esto porque nunca lo llamamos directamente
                    if (preg_match('/^'.$pluginName.'App/', $file)){
                        unset($files[$f]);
                    } else {
                                    if (!App::import('Controller', $pluginName.'.'.$file))
                                    {
                                        debug('Error importando el archivo '.$file.' para el plugin '.$pluginName);
                                    }

                        // Ahora le agregamos el nombre del plugin al inicio
                        // Esto lo necesitamos para poder obtener los nombres
                        // de los métodos
                        $files[$f] = $file;
                    }
                    break;
                }
            }
        }

        return $files;
    }


}
?>
